﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Birkelund.QueryStrings
{
    /// <summary>
    /// Implements a Des algorithm
    /// </summary>
    public class DesEncryptionImpl : ISymmetricEncryption
    {
        private readonly byte[] bytes;

        /// <summary>
        /// Constructor which initializes 
        /// </summary>
        public DesEncryptionImpl() : this("_qSEKCoL")
        {
        }

        /// <summary>
        /// Initializor
        /// </summary>
        /// <param name="key"></param>
        public DesEncryptionImpl(string key)
        {
            bytes = Encoding.ASCII.GetBytes(key);
        }

        /// <summary>
        /// Encrypt a string
        /// </summary>
        /// <param name="clearText"></param>
        /// <returns>Returns encrypted text or throws an exception on error</returns>
        public string Encrypt(string clearText)
        {
            if (string.IsNullOrEmpty(clearText))
            {
                return clearText;
            }

            using (DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider())
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoProvider.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write))
                    {
                        using (StreamWriter writer = new StreamWriter(cryptoStream))
                        {
                            writer.Write(clearText);
                            writer.Flush();
                            cryptoStream.FlushFinalBlock();
                            cryptoStream.Flush();

                            return Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Decrypt an encrypted string
        /// </summary>
        /// <param name="encryptedText">Encrypted string</param>
        /// <returns>Returns cleattext or throws an exception on error</returns>
        public string Decrypt(string encryptedText)
        {
            if (string.IsNullOrEmpty(encryptedText))
            {
                return encryptedText;
            }

            using (DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider())
            {
                using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(encryptedText)))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoProvider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read))
                    {
                        using (StreamReader reader = new StreamReader(cryptoStream))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                }
            }
        }
    }
}
